import { reactive, watch } from "vue";
import * as THREE from "three";
import * as TWEEN from "@tweenjs/tween.js";
import { Octree } from "three/examples/jsm/math/Octree";
import { OctreeHelper } from "three/examples/jsm//helpers/OctreeHelper.js";
import { Player } from "./player";
import { Time } from "./time";
import { loadGLTF } from "../loader";

export const libraryState: {
  spriteTarget: any; //移动动画的标签
  tweenPosition: any; //tween动画移动的位置对象
  player: any; //用户视角对象
  joyStick: any; //游戏手柄对象
  isMobile: boolean; //是否是移动端
  sceneIndex: number; ///当前场景编号
  fileUrls: any[]; //模型资源列表
  isEnter: boolean; //是否进入区域
  isModelLoaded: boolean; //模型是否加载完成
} = reactive({
  spriteTarget: null,
  tweenPosition: null,
  player: null,
  joyStick: null,
  isMobile: false,
  sceneIndex: 1,
  fileUrls: [
    "./model/library.glb",
    "./model/collision-world.glb",
    "./model/world.glb",
    "./model/modular_dungeon.glb",
  ],
  isEnter: false,
  isModelLoaded: false,
});

export class Library {
  modelObj: any; //当前模型对象
  scene: any; //当前场景
  camera: any; //当前相机
  controls: any; //当前控制器
  tweenPosition: any; //tween动画移动的位置对象
  tweenRotation: any; //tween动画移动的方向对象
  octree: any; //八叉树
  deltaTime: any; //自定义帧刷新时间
  canvasDom: any; //上下文对象
  cube: any; //用于区域判断

  textMesh: any;
  dotMesh: any;
  backMesh: any;
  raycaster: any = new THREE.Raycaster();

  constructor(scene: any, camera: any, controls: any, model?: number) {
    this.scene = scene;
    this.camera = camera;
    this.controls = controls;
    this.canvasDom = document.getElementById("library");

    this.tweenPosition = null;
    this.tweenRotation = null;
    libraryState.isMobile = /Mobile/i.test(navigator.userAgent);

    //加载模型
    this.changeModel(model);
    //添加事件
    if (libraryState.isMobile) {
      this.addTouchEvent();
    } else {
      this.addMouseEvent();
    }
    // 处理标签点击事件
    this.addClick();
    // 初始化自定义帧时间
    this.initTime();
    this.addEnterArea();
  }
  start(delta: any) {
    // this.deltaTime = Math.min(0.05, delta); //返回0.05, delta之间最小值
    // 更新方法
    this.tweenPosition && this.tweenPosition.update();
    this.tweenRotation && this.tweenRotation.update();
    // this.player &&  this.player.update(this.deltaTime);
    // 使用自定义计时器
    libraryState.player && libraryState.player.update(this.deltaTime.delta);
    this.deltaTime && this.deltaTime.update();
    this.isEnterArea();
  }
  initTime() {
    this.deltaTime = new Time();
  }
  loadModel(url, modelId) {
    // 加载模型，并渲染到画布上
    loadGLTF(url).then((object: any) => {
      console.log(
        "处理模型-------------------",
        new Date().getMinutes() + "分" + new Date().getSeconds() + "秒"
      );

      libraryState.isModelLoaded = true;
 
      this.modelObj = object.scene;
      this.scene.add(this.modelObj);

      if(modelId==1){
        this.modelObj.scale.set(130, 130, 130);
      }

      try {
        //八叉树
        this.octree = new Octree();
        this.octree.fromGraphNode(this.modelObj); // 通过Octree对象来构建节点
        // OctreeHelper
        // const helper = new OctreeHelper(this.octree);
        // helper.visible = true;
        // this.scene.add(helper);
      } catch (error) {
        console.log("octree-error", error);
      }

      //添加玩家
      libraryState.player = new Player(this.scene, this.camera, this.octree);
    });
  }
  changeModel(index) {
    switch (index) {
      case 1:
        this.loadModel(libraryState.fileUrls[0], index); //图书馆
        this.addSpriteTag();
        this.addSpriteTag2();
        this.addSpriteTag4();
        break;
      case 2:
        this.loadModel(libraryState.fileUrls[1], index); //泳池
        this.addSpriteTag3();
        break;
      case 3:
        this.loadModel(libraryState.fileUrls[2], index); //盒子世界
        break;
      case 4:
        this.loadModel(libraryState.fileUrls[3], index);//城堡
        this.addSpriteTag();
        this.addSpriteTag2();
        break;
    }
  }
  addClick() {
    if (libraryState.isMobile) {
      this.canvasDom.ontouchstart = (event) => {
        event.preventDefault();
        event.stopPropagation();
        this.addTextMeshClick({
          x: event.touches[0].pageX,
          y: event.touches[0].pageY,
        });
      };
    } else {
      this.canvasDom.onclick = (event) => {
        event.preventDefault();
        event.stopPropagation();
        this.addTextMeshClick({
          x: event.pageX,
          y: event.pageY,
        });
      };
    }
  }
  addSpriteTag() {
    const textmap = new THREE.TextureLoader().load("./img/auto.png");
    const materialObj = new THREE.SpriteMaterial({
      map: textmap,
    });
    this.textMesh = new THREE.Sprite(materialObj);
    this.textMesh.position.set(10, 2.2, 0.2);
    this.textMesh.rotateY(-Math.PI / 2); //旋转90度
    this.textMesh.name = "text";
    this.scene.add(this.textMesh);
    //点击事件和指针控制器冲突
    // this.textMesh.addEventListener(
    //   "click",
    //   this.moveCameraToMeshPosition(this.textMesh)
    // );
  }
  addSpriteTag2() {
    const textmap = new THREE.TextureLoader().load("./img/change1.png");
    const materialObj = new THREE.SpriteMaterial({
      map: textmap,
    });
    this.dotMesh = new THREE.Sprite(materialObj);
    this.dotMesh.position.set(
      -56.22548526525499,
      3.3533313327117753,
      -20.832882390717664
    );
    this.dotMesh.scale.set(1.9, 1, 1);
    this.dotMesh.name = "text";
    this.scene.add(this.dotMesh);
  }
  addSpriteTag4() {
    const textmap = new THREE.TextureLoader().load("./img/change2.png");
    const materialObj = new THREE.SpriteMaterial({
      map: textmap,
    });
    this.dotMesh = new THREE.Sprite(materialObj);
    this.dotMesh.position.set(
      -54.91447054922031,
      2.964092161593259,
      -14.926201347382301
    );
    this.dotMesh.scale.set(2.2, 1, 1);
    this.scene.add(this.dotMesh);
  }
  addSpriteTag3() {
    const textmap = new THREE.TextureLoader().load("./img/back.png");
    const materialObj = new THREE.SpriteMaterial({
      map: textmap,
    });
    this.backMesh = new THREE.Sprite(materialObj);
    this.backMesh.position.set(0, 0, 0);
    this.backMesh.rotateY(-Math.PI / 2); //旋转90度
    this.backMesh.name = "back";
    this.scene.add(this.backMesh);
  }
  addTextMeshClick(obj) {
    if (!libraryState.isMobile) this.controls.lock();
    const raycaster = new THREE.Raycaster();
    const mouse = new THREE.Vector2();
    mouse.x = (obj.x / window.innerWidth) * 2 - 1;
    mouse.y = -(obj.y / window.innerHeight) * 2 + 1;
    raycaster.setFromCamera(mouse, this.camera);
    console.log(obj, mouse, window.innerWidth);

    // let currentP = new THREE.Vector3();
    // const intersects_ = raycaster.intersectObjects(this.scene.children, true);
    // if (intersects_.length > 0) {
      // var intersectPoint = intersects_[0].point;
      // console.log("获取点击物体", intersects_[0].object);
      // console.log("获取点击屏幕位置的世界坐标:", intersectPoint);
      // currentP.copy(intersectPoint); //为触摸点得世界坐标
    // }

    if (this.textMesh) {
      const intersects = raycaster.intersectObjects([this.textMesh]);
      if (intersects.length > 0) {
        console.log("点击标签-移动");
        // 处理点击事件
        this.moveCameraToMeshPosition(this.textMesh);
      } else if (!libraryState.isMobile && !this.controls?.isLocked) {
        // this.controls.lock();
      }
    }

    if (this.dotMesh) {
      const intersects2 = raycaster.intersectObjects([this.dotMesh]);
      if (intersects2.length > 0) {
        console.log("点击标签-切换场景2");
        libraryState.sceneIndex = 2;
      } else if (!libraryState.isMobile && !this.controls?.isLocked) {
        // this.controls.lock();
      }
    }

    if (this.backMesh) {
      const intersects3 = raycaster.intersectObjects([this.backMesh]);
      if (intersects3.length > 0) {
        console.log("点击标签-切换场景1");
        libraryState.sceneIndex = 1;
      } else if (!libraryState.isMobile && !this.controls?.isLocked) {
        // this.controls.lock();
      }
    }
  }
  moveCameraToMeshPosition(mesh) {
    // 获取 mesh 的世界坐标
    const targetPosition = new THREE.Vector3();
    mesh.getWorldPosition(targetPosition);
    // 定义相机移动的目标位置
    const target = new THREE.Vector3(targetPosition.x, 0, targetPosition.z);
    libraryState.spriteTarget = target;
    libraryState.player.update(this.deltaTime);
  }
  addMouseEvent() {
    let mouseX;
    let mouseY;

    document.onmousedown = (event) => {
      event.preventDefault();
      mouseX = event.pageX;
      mouseY = event.pageY;
    };

    document.onmousemove = (event) => {
      event.preventDefault();
      if (mouseX && mouseY) {
        var deltaX = event.pageX - mouseX;
        var deltaY = event.pageY - mouseY;
        mouseX = event.pageX;
        mouseY = event.pageY;

        // 根据触摸事件的移动量调整相机的角度
        this.camera.rotation.y -= deltaX * 0.003; //左右旋转
        this.camera.rotation.x -= deltaY * 0.003; //俯仰旋转
      }
    };

    document.onmouseup = (event) => {
      event.preventDefault();
      mouseX = null;
      mouseY = null;
    };
  }
  addTouchEvent() {
    let touchX;
    let touchY;
    document.ontouchmove = (event) => {
      event.preventDefault();
      if (touchX && touchY) {
        // if (this.handleMobileScroll(event.touches)) return;

        var deltaX = event.touches[0].pageX - touchX;
        var deltaY = event.touches[0].pageY - touchY;
        touchX = event.touches[0].pageX;
        touchY = event.touches[0].pageY;

        // 根据触摸事件的移动量调整相机的角度
        // this.camera.rotation.y -= deltaX * 0.003; //左右旋转
        // this.camera.rotation.x -= deltaY * 0.003; //俯仰旋转
        this.camera.rotation.y -= deltaY * 0.003; //左右旋转
        this.camera.rotation.x += deltaX * 0.003; //俯仰旋转
      } else {
        touchX = event.touches[0].pageX;
        touchY = event.touches[0].pageY;
      }
    };
    document.ontouchend = (event) => {
      // 当触摸结束时，重置触摸起始点
      touchX = null;
      touchY = null;
    };
  }
  addEnterArea() {
    const textmap = new THREE.TextureLoader().load("./img/change.png");
    const geometry = new THREE.BoxGeometry(0.1, 2, 2);
    const material = new THREE.MeshBasicMaterial({
      map: textmap,
    });
    this.cube = new THREE.Mesh(geometry, material);
    this.cube.position.set(-6, 1, 0);
    this.scene.add(this.cube);
  }
  isEnterArea() {
    this.raycaster.near = 0.1;
    this.raycaster.far = 1;
    const middlePoint = new THREE.Vector2(0, 0);
    this.raycaster.setFromCamera(middlePoint, this.camera);
    const result = this.raycaster.intersectObjects([this.cube]);
    if (result.length > 0) {
      libraryState.isEnter = true;
    } else {
      libraryState.isEnter = false;
    }
  }
}
